home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Graphics⁄Sound / soundlab stuff / SIHuff.C < prev    next >
Encoding:
Text File  |  1986-05-24  |  5.6 KB  |  207 lines  |  [TEXT/EDIT]

  1. #Options Z
  2.  
  3. // mod 9 30 85 tsh - decode only version for playing sound
  4. // mod 9 16 85 tsh - completely redo I/O buffering to be consistent with
  5. //    previous SoundCap, make startup of compressed file work,
  6. //    eliminate MAZlib:BufIO
  7. // MOD 09-01-85 MAZ - huffman variable-bit-width code
  8. //         "  - file compression routines created
  9.  
  10. #include "MacCdefs.h"
  11. #include "MAZlib.h"
  12. #include "OSio.h"
  13. #include "pbDefs.h"
  14.  
  15. // huffman compression of deltas, values
  16. #define type_value 0
  17. #define type_delta 1
  18.  
  19. #asm
  20.     include    SysEquX.D
  21.     include    MacTraps.D
  22. #endasm
  23.  
  24. // used in the file
  25. typedef struct
  26.     {
  27.     short int dict_leftson;
  28.     short int dict_rightson;
  29.     } dictent;
  30.  
  31. // the dictionary packed - packed into on write, used during decode step
  32. dictent dictionary[511];
  33.  
  34. // huffman total count
  35. long int huffcount;
  36.  
  37. // IO packet
  38. ioParam huffIo;
  39.  
  40. // open file, read the file header and decide allocation.
  41. // returns -1 if not compressed
  42. long int huffman_readsize(filename, refnum)
  43.   char *filename;
  44.   short refnum;
  45.     {
  46.     long lbuff[2];
  47.  
  48.     // open the input file
  49.     huffIo.ioNamePtr = filename;
  50.     huffIo.ioVRefNum = refnum;    // default volume
  51.     huffIo.ioVersNum = 0;    // normal version
  52.     huffIo.ioPermssn = 1;    // reading
  53.     huffIo.ioMisc = 0;        // no buffer
  54.     huffIo.ioResult = 1;
  55.     PBOpen(&huffIo, false);
  56.     if (huffIo.ioResult < 0)
  57.     return(huffIo.ioResult);
  58.     // read the header (2 long words)
  59.     huffIo.ioBuffer = (char *)lbuff;
  60.     huffIo.ioReqCount = 8;    // 2 longwords
  61.     huffIo.ioPosMode = 1;    // absolute
  62.     huffIo.ioPosOffset = 0;    // from the beginning
  63.     huffIo.ioResult = 1;
  64.     PBRead(&huffIo, false);
  65.     // read the compression field.
  66.     if (lbuff[0] != 'HCOM')
  67.     return(-1);
  68.     huffcount = lbuff[1];
  69.     return(huffcount);
  70.     }
  71.  
  72. huffman_close()
  73.     {
  74.     PBClose(&huffIo, false);
  75.     }
  76.  
  77. // read the huffman file and undo it into a flat sample buffer
  78. // after doing huffman_readsize()
  79. int huffman_input(bptr, psampling, iobuff, iocnt)
  80.   unsigned char *bptr;
  81.   long int *psampling;
  82.   char *iobuff;
  83.   long int iocnt;
  84.     {
  85.     unsigned char first_sample, *buffer, *p;
  86.     short int dictsz;
  87.     long int checksum, i, csum, count, type;
  88.     long lbuff[4];
  89.     char twoc[2];
  90.  
  91.     count = huffcount;
  92.     buffer = bptr;
  93.     // read in 14 bytes
  94.     huffIo.ioBuffer = (char *)lbuff;
  95.     huffIo.ioReqCount = 14;    // 3 longwords, 1 word
  96.     huffIo.ioPosMode = 0;    // relative to mark
  97.     PBRead(&huffIo, false);
  98.     csum = lbuff[0];     // read the checksum
  99.     type = lbuff[1];    // read the compression type (always delta)
  100.     *psampling = lbuff[2]; // return the sampling rate
  101.     // read the huffman dictionary up front into 'dictionary'
  102.     dictsz = *(short *)(&lbuff[3]); // read dictionary size
  103.     // read in the dictionary
  104.     huffIo.ioBuffer = (char *)dictionary;
  105.     huffIo.ioReqCount = sizeof(dictent)*dictsz;    // size to read
  106.     huffIo.ioPosMode = 0;    // relative to mark
  107.     PBRead(&huffIo, false);
  108.     // preshift dictionary entries to speed processing
  109.     for (i=0; i<511; i++)
  110.       if (dictionary[i].dict_leftson >= 0)
  111.     {
  112.     dictionary[i].dict_leftson <<= 2;
  113.     dictionary[i].dict_rightson <<= 2;
  114.     }
  115.     // read first sample in
  116.     p = (unsigned char *)lbuff;
  117.     huffIo.ioBuffer = (char *)p;
  118.     huffIo.ioReqCount = 2;    // 2 characters
  119.     huffIo.ioPosMode = 0;    // relative to mark
  120.     PBRead(&huffIo, false);
  121.     p++;    // ignor pad byte twoc[0]
  122.     first_sample = *p++;
  123.     // process rest of buffer
  124.     checksum = unhuff_buffer(buffer, count, first_sample, iobuff, iocnt);
  125.     // test the checksum
  126.     if (checksum != csum)
  127.     return(-1);
  128.     // checksum OK, read compressed readin
  129.     return(0);
  130.     }
  131.  
  132. // huffman decode step (reads and decodes data)
  133. long int unhuff_buffer(buffer,count,first_sample,iobuffer,iocnt)
  134.   unsigned char *buffer;    // D0
  135.   long int count;        // D1
  136.   unsigned char first_sample;    // D2
  137.   char *iobuffer;        // D3
  138.   long int iocnt;        // D4
  139.     {
  140. #asm
  141. iocnt    EQU    -4
  142. iobuff    EQU    -8
  143. stksiz    EQU    -12
  144.  
  145.     LINK    A6,#stksiz
  146.     MOVEM.L    D1-D7/A0-A4,-(SP)
  147.     MOVE.L    D3,iobuff(A6)    ;save I/O buffer
  148.     MOVE.L    D4,iocnt(A6)    ;save I/O buffer size
  149.     MOVE.L    D0,A0        ; OUTPUT POINTER TO A0
  150.     MOVE.B    D2,(A0)+    ; OUTPUT FIRST SAMPLE
  151.     SUBQ.L    #1,D1        ; DECREMENT COUNT
  152.     MOVE.L    D1,D7        ; INTO R7
  153.     MOVEQ    #0,D0
  154.     MOVE.L    D0,A3        ; ZERO LONGWORD CHECKSUM
  155. ; POINT TO DICTIONARY ROOT - READY FOR PARSE
  156.     LEA    dictionary(A5),A2
  157.     MOVEQ    #0,D4        ; DICTIONARY CURRENT POINTER
  158.     BRA.S    BUFREAD        ; jump into loop    
  159.  
  160. ; process a bit and branch further into Huffman tree
  161. BITLP:    LSL.L    #1,D5        ; SHIFT OVER 1 BIT
  162.     BCC.S    ZEROBIT        ; BRANCH IF LEFT SON
  163.     ADDQ.W    #2,D4        ; POINT TO RIGHT SON
  164. ZEROBIT: MOVE.W    0(A2,D4.W),D4    ; LOAD SON
  165.     MOVE.W    0(A2,D4.W),D0    ; CHECK FOR LEAF
  166.     DBMI    D3,BITLP
  167.     BGE.S    BUFWD        ; TEST FOR BIT COUNTER EXPIRED
  168. ; at end of huffman encoding, sum the delta and output char
  169.     ADD.W    2(A2,D4.W),D2    ; COMPUTE NEXT CHARACTER
  170.     MOVE.B    D2,(A0)+    ; OUTPUT NEXT SAMPLE
  171. ; prepare for next sample
  172.     MOVEQ    #0,D4        ; DICTIONARY CURRENT POINTER
  173.     SUBQ.L    #1,D7        ; DONE COLLECTING?
  174.     BLE.S    EOBLP
  175.     TST.W    D3
  176.     BMI.S    BUFWD
  177. ; loop to next bit
  178. BITCNT:    DBF    D3,BITLP    ; NEXT BIT FROM INPUT
  179.  
  180. ; GET ANOTHER LONG FROM THE INPUT BUFFER
  181. BUFWD:    SUBQ.L    #4,D6        ; we process 4 bytes at a time
  182.     BGT.S    BUFGO        ; NO REFILL NEEDED
  183.  
  184. ; READ ANOTHER BUFFER IN
  185. BUFREAD: MOVEM.L A0/D0-D2,-(SP) ;save ac's
  186.     LEA    huffIo(A5),A0    ;get our packet
  187.     MOVEA.L    iobuff(A6),A1    ;reset buffer ptr
  188.     MOVE.L    iocnt(A6),D6    ;reset buffer count
  189.     MOVE.L    A1,ioBuffer(A0)    ;get buffer
  190.     MOVE.L    D6,ioReqCount(A0) ;get requested count
  191.     CLR.W    ioPosMode(A0)    ;relative positioning
  192.     _Read
  193.     MOVEM.L    (SP)+,A0/D0-D2    ;restore ac's
  194.     
  195. BUFGO:    MOVE.L    (A1)+,D5
  196.     ADD.L    D5,A3        ; UPDATE CHECKSUM
  197.     MOVEQ    #31,D3        ; BITS IN LONG (-1 FOR DBF)
  198.     BRA.S    BITLP
  199.  
  200. ; ALL DONE
  201. EOBLP:    MOVE.L    A3,D0        ; RETURN CHECKSUM
  202.     MOVEM.L    (SP)+,D1-D7/A0-A4
  203.     UNLK    A6
  204.     RTS
  205. #endasm
  206.     }
  207.